package nc.hrpbctp.control.bs;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.ArrayUtils;

import nc.bs.dao.BaseDAO;
import nc.bs.framework.common.NCLocator;
import nc.bs.framework.exception.ComponentException;
import nc.bs.logging.Logger;
import nc.bs.trade.business.HYPubBO;
import nc.bs.uap.lock.PKLock;
import nc.hrpbctp.control.bs.execute.ExecForAddExec;
import nc.hrpbctp.control.bs.execute.ExecForAddOccu;
import nc.hrpbctp.control.bs.execute.ExecForSubExec;
import nc.hrpbctp.control.bs.execute.ExecForSubOccu;
import nc.hrpbctp.control.bs.pushdata.PushDataForDelete;
import nc.hrpbctp.control.bs.pushdata.PushDataForInsert;
import nc.hrpbctp.control.bs.pushdata.PushDataForUpdate;
import nc.hrpbctp.control.bs.pushdata.PushDataForUpdateAddFreeze;
import nc.hrpbctp.control.bs.pushdata.PushDataForUpdateReduceFreeze;
import nc.hrpbctp.control.bs.utils.BctpControlBsUtils;
import nc.hrpbctp.control.bs.utils.BctpControlDimValueMatchUpUtils;
import nc.hrpbctp.control.pub.BctpControlAmountCheckException;
import nc.hrpbctp.control.pub.IBcptControl;
import nc.hrpbctp.control.pub.IBctpControlOperateStrategy;
import nc.hrpbctp.control.pub.IBctpControlPlugin;
import nc.hrpbctp.control.pub.utils.BctpControlMessageUtils;
import nc.hrpbctp.control.pub.utils.BctpControlPubUtils;
import nc.impl.pubapp.pattern.database.DBTool;
import nc.impl.pubapp.pub.smart.BatchSaveAction;
import nc.itf.hrpbctp.busictrl.busictrl.IBusiCtrlVOService;
import nc.itf.uif.pub.IUifService;
import nc.jdbc.framework.processor.BeanListProcessor;
import nc.uif.pub.exception.UifException;
import nc.vo.bd.meta.BatchOperateVO;
import nc.vo.bd.pub.EnableStateEnum;
import nc.vo.hrpbctp.busctrltype.BusictrlTypeVO;
import nc.vo.hrpbctp.busibillconfig.AggBusiConfigVO;
import nc.vo.hrpbctp.busibillconfig.BusiConfigBillactionVO;
import nc.vo.hrpbctp.busibillconfig.BusiConfigDimmapVO;
import nc.vo.hrpbctp.busibillconfig.BusiConfigPluginregVO;
import nc.vo.hrpbctp.busibillconfig.BusiConfigVO;
import nc.vo.hrpbctp.busictrl.AggBusiCtrlVO;
import nc.vo.hrpbctp.busictrl.BusiCtrlDataVO;
import nc.vo.hrpbctp.busictrl.BusiCtrlDetailVO;
import nc.vo.hrpbctp.busictrl.BusiCtrlRuleVO;
import nc.vo.hrpbctp.busictrldim.AggBusiCtrlDimVO;
import nc.vo.hrpbctp.busictrldim.BusiCtrlDimBVO;
import nc.vo.hrpbctp.busictrldim.BusiCtrlDimVO;
import nc.vo.hrpbctp.busictrlscheme.BusictrlSchemeBVO;
import nc.vo.hrpbctp.busictrlscheme.BusictrlSchemeVO;
import nc.vo.hrpbctp.ctrldim.CtrlDimVO;
import nc.vo.hrpbctp.enums.BusiConfigTypeEnum;
import nc.vo.hrpbctp.enums.BusisceneModeEnum;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BusinessException;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDouble;
import nc.vo.pubapp.pattern.pub.MapList;
import nc.vo.pubapp.pattern.pub.SqlBuilder;
import nc.vo.pubapp.util.VOSortUtils;

/**
 *业务控制操作基础类
 *
 * @author WW
 *
 */
public abstract class BctpControl_Base implements IBcptControl {

	/**
	 * 私有化无参构造方法
	 */
	private BctpControl_Base() {
	}
	public BctpControl_Base(AggBusiConfigVO aggBusiConfigVo,AggBusiCtrlDimVO aggBusiCtrlDim, BusictrlSchemeVO ctrlScheme,BusictrlSchemeBVO ctrlSchemeb)
			throws BusinessException {


		this.aggBusiConfigVo = aggBusiConfigVo;
		this.busiConfigVo = aggBusiConfigVo.getParentVO();

		this.busiCtrlDim = aggBusiCtrlDim.getParentVO();
		this.busiCtrlDims = (BusiCtrlDimBVO[])aggBusiCtrlDim.getChildren(BusiCtrlDimBVO.class);
		this.ctrlDims = BctpControlBsUtils.queryCtrlDims(busiCtrlDims);

		this.ctrlScheme = ctrlScheme;
		this.ctrlSchemeb = ctrlSchemeb;

		if (aggBusiConfigVo == null || ctrlScheme == null || ctrlDims == null || ctrlDims.length == 0)
			throw new BusinessException("请在构造参数中传入有效的业务单据配置信息、业务控制维度和业务控制方案信息。");

		//总账执行时，找不到业务控制不抛错，跳过即可
//		if("C0".equals(aggBusiConfigVo.getParentVO().getBusibilltype())) {
//			this.isNoCtrlDataCtrl = false;
//		}


	}

	//定义精度
	public int digit = 2;

	// 返回值
	private Map<String, String> resultMessage = new HashMap<String, String>();

	/**
	 * 参数单据
	 */
	protected AggregatedValueObject paramVo;
	/**
	 * 原始参数单据
	 */
	protected AggregatedValueObject oriParamVo;
	/**
	 * 参数单据转换的业务控制信息和业务控制规则信息
	 */
	private AggBusiCtrlVO aggBusiCtrlVoFromParam = null;
	private AggBusiCtrlVO oriAggBusiCtrlVoFromParam = null;
	//是否参与业务控制
	UFBoolean isJoinCtrl = UFBoolean.TRUE;
	//无业务控制数据时是否控制
	boolean isNoCtrlDataCtrl = true;
	/**
	 * 业务单据配置
	 */
	AggBusiConfigVO aggBusiConfigVo;// 业务单据配置aggvo
	BusictrlSchemeVO ctrlScheme;//业务控制方案信息
	BusictrlSchemeBVO ctrlSchemeb;//业务控制方案明细信息
	BusictrlTypeVO busictrlType;//当前操作的业务控制类型
	BusiCtrlDimVO busiCtrlDim;//启用的业务控制维度表头
	BusiCtrlDimBVO[] busiCtrlDims;//启用的业务控制维度明细
	CtrlDimVO[] ctrlDims;//使用到的控制维度定义档案
	String ctrlDimStr;//控制维度字符描述

	Map<String, BusiCtrlDimBVO> busiCtrlDimMap = new HashMap<String, BusiCtrlDimBVO>();//业务控制维度设置中启用的维度
	List<BusiCtrlDimBVO> busiCtrlDimList_matchup = new ArrayList<BusiCtrlDimBVO>();//需要向上级匹配的业务控制维度设置
	Map<String, CtrlDimVO> ctrlDimMap = new HashMap<String, CtrlDimVO>();//控制维度定义



	protected BusiConfigVO busiConfigVo;// 业务单据配置表头
	private BusiConfigDimmapVO[] billMapVos;// 业务单据配置-维度映射
	private BusiConfigBillactionVO billActionVo;// 业务单据配置-动作配置(当前执行的动作配置)
	private Map<String, BusiConfigBillactionVO> billActionMap;// 业务单据配置-所有动作的配置，用于动作关联时使用
	@SuppressWarnings("rawtypes")
	private List<IBctpControlOperateStrategy> operators = new ArrayList<IBctpControlOperateStrategy>();// 当前动作配置中需要执行的操作
	protected List<IBctpControlPlugin> beforePlugins = new ArrayList<IBctpControlPlugin>();// 前插件
	protected List<IBctpControlPlugin> afterPlugins = new ArrayList<IBctpControlPlugin>();// 后插件

	// 以下信息记录当前执行业务控制的集团、组织、年度、一级业务控制类型
//	private String pk_group;
//	private String pk_org;
//	private String billtype;
//	private String transtype;
	protected String actionCode;


	/**
	 * 控制规则：key ： idcode
	 */
	private Map<String, BusiCtrlRuleVO> ctrlRuleMapFromParam = null;
	private Map<String, BusiCtrlRuleVO> oriCtrlRuleMapFromParam = null;

	/**
	 * 数据库中存储的控制规则，以及分组控制规则 key:idcode
	 */
	private Map<String, BusiCtrlRuleVO> ctrlRuleMapFromDb = null;
	// 合并控制规则：key ：业务控制信息表头主键 + 合并分组编号
	private MapList<String, BusiCtrlRuleVO> combCtrlRuleMaplFromDb = null;

	/**
	 * 数据库中存储的控制数据，以及控制数据idcode对应的控制信息表头id key:idcode
	 */
	private Map<String, BusiCtrlDataVO> ctrlDataMapFromDb = null;
	/**
	 * 匹配上级的控制数据
	 * 数据库中存储的控制数据，以及控制数据idcode对应的控制信息表头id key:idcode
	 */
	private Map<String, BusiCtrlDataVO> ctrlDataMapFromDb_matchup = null;
	/**
	 * 匹配上级的控制数据idcode对照
	 *key：参数ctrldata的idcode，value：匹配上级ctrldata的idcode
	 */
	private Map<String,String> ctrlDataIdCodeMap_matchup = new HashMap<String,String>();
	/**
	 * 数据库操作对象
	 */
	BctpControlOperateDataBean operateData = null;

	/**
	 * 用户扩展的变量
	 */
	private Map<String, Object> extendObjMap = new HashMap<String, Object>();

	/**
	 *业务数据操作
	 *
	 * @param pk_group   集团
	 * @param pk_org     组织
	 * @param actionCode
	 * @param paramVo
	 * @param oriParamVo 原始参数单据（记录修改保存时修改前的数据）
	 * @return
	 * @throws BusinessException
	 */
	@Override
	public Object operate(String pk_group, String pk_org, String actionCode, AggregatedValueObject paramVo,
						  AggregatedValueObject oriParamVo) throws BusinessException {

		this.digit = BctpControlBsUtils.getDigit(pk_org, this.busiConfigVo.getBusiscenemode());

		this.actionCode = actionCode;
		this.paramVo = paramVo;
		this.oriParamVo = oriParamVo;

		String[] idCodes = new String[0];
		try {

			/*
			 * 处理参数信息
			 */
			processParam();

			// 找不到对应动作时直接返回
			if (this.billActionVo == null)
				return this.getResultMessage();

			//参数中未获取明细数据直接返回
			boolean hasCtrlData = false;
			if(this.aggBusiCtrlVoFromParam != null) {
				BusiCtrlDataVO[] ctrlDatas = (BusiCtrlDataVO[])this.aggBusiCtrlVoFromParam.getChildren(BusiCtrlDataVO.class);
				if( ctrlDatas != null && ctrlDatas.length > 0)
					hasCtrlData = true;
			}
			if (hasCtrlData == false && this.oriAggBusiCtrlVoFromParam != null) {
				BusiCtrlDataVO[] ctrlDatas = (BusiCtrlDataVO[])this.oriAggBusiCtrlVoFromParam.getChildren(BusiCtrlDataVO.class);
				if( ctrlDatas != null && ctrlDatas.length > 0)
					hasCtrlData = true;
			}
			if(hasCtrlData == false)
				return null;


			/*
			 * 初始化业务控制操作处理器
			 */
			initProcessors();

			/*
			 * 初始化插件
			 */
			initPlugins(aggBusiConfigVo);

			/*
			 * 前插件处理
			 */
			Object pluginReturnValue = processPlugin_before();
			if(pluginReturnValue instanceof Boolean) {//Boolean类型的返回结果代表要中断后续执行
				return this.getResultMessage();
			}

			/*
			 * 初始化相关业务控制规则 返回的idcodes中包含了分组控制相关的所有业务控制明细的idcodes
			 */
//			BusiCtrlDetailVO[] ctrlDetails = (BusiCtrlDetailVO[]) aggBusiCtrlVoFromParam
//					.getChildren(BusiCtrlDetailVO.class);
//			String[] idcodes = BctpControlPubUtils.getFieldUniqueValues(ctrlDetails, "idcode");
//			String[] oriIdcodes = new String[0];
//			if (oriAggBusiCtrlVoFromParam != null) {
//				BusiCtrlDetailVO[] oriCtrlDetails = (BusiCtrlDetailVO[]) oriAggBusiCtrlVoFromParam
//						.getChildren(BusiCtrlDetailVO.class);
//				oriIdcodes = BctpControlPubUtils.getFieldUniqueValues(oriCtrlDetails, "idcode");
//			}
			BusiCtrlDataVO[] ctrlDatas = (BusiCtrlDataVO[]) aggBusiCtrlVoFromParam
					.getChildren(BusiCtrlDataVO.class);

//			String[] oriIdcodes = new String[0];
			BusiCtrlDataVO[] allCtrlDatas = ctrlDatas;
			if (oriAggBusiCtrlVoFromParam != null) {
				BusiCtrlDataVO[] oriCtrlDatas = (BusiCtrlDataVO[]) oriAggBusiCtrlVoFromParam
						.getChildren(BusiCtrlDataVO.class);

				allCtrlDatas = (BusiCtrlDataVO[]) ArrayUtils.addAll(ctrlDatas, oriCtrlDatas);

			}

			if(allCtrlDatas == null || allCtrlDatas.length == 0)
				return null;

			idCodes = BctpControlPubUtils.getFieldUniqueValues(allCtrlDatas, "idcode");

			/*
			 * 向上级匹配到的业务控制数据
			 * 推送数据时不需要向上匹配
			 */
			if(this.busiConfigVo.getBusiconfigtype().equals(BusiConfigTypeEnum.SKDJ.toStringValue())) {
				ctrlDataMapFromDb_matchup = BctpControlDimValueMatchUpUtils.matchUp(this,ctrlDimMap,busiCtrlDimList_matchup,allCtrlDatas,ctrlDataIdCodeMap_matchup,true);
				String[] idCodes_matchup = ctrlDataMapFromDb_matchup.keySet().toArray(new String[0]);
				idCodes = ArrayUtils.addAll(idCodes, idCodes_matchup);
			}


			// 因为涉及到分组控制，所以要把分组控制相关的所有业务控制维度都查询出来
			String[] newIdCodes = initCtrlRuleFromDB(idCodes);
			// 推送新增业务控制时数据库中无相关记录，所以此处次要进行处理
			idCodes = (newIdCodes == null || newIdCodes.length == 0) ? idCodes : newIdCodes;

			/*
			 * 加锁：并发时最多尝试5次，每次间隔50毫秒 将每一条控制规则的idcode进行加锁
			 */
			int round = 0;
			boolean locked = false;
			while (locked == false && round <= 5) {
				round++;
				locked = PKLock.getInstance().acquireBatchLock(idCodes, null, null);

				if (locked == false)
					Thread.sleep(50);
			}
			if (locked == false)
				throw new BusinessException("出现并发，请重新操作");

			/*
			 * 初始化相关业务控制数
			 */
			initCtrlDataFromDB(idCodes);

			/*
			 * 处理数据
			 */
			operateData = new BctpControlOperateDataBean();
			processData(operateData);

			/*
			 * 检查业务控制操作结果
			 */
			processControl(operateData);

			/*
			 * 处理操作返回信息
			 */
			boolean checkResult = processControlMessage();
			if (checkResult == false)
				return this.getResultMessage();

			/*
			 * 数据库操作
			 */
			processDb(operateData);

			/*
			 * 后插件处理
			 */
			processPlugin_after();

		} catch(BctpControlAmountCheckException e) {

			throw new BctpControlAmountCheckException(this.getErrorMessageTitle() + "\n" + e.getMessage());

		} catch (Exception e) {

			throw new BusinessException(this.getErrorMessageTitle() + "\n" + e.getMessage());

		} finally {

			/*
			 * 释放锁
			 */
			if (idCodes != null && idCodes.length > 0)
				PKLock.getInstance().releaseBatchLock(idCodes, null, null);

		}

		return this.getResultMessage();

	}

	/**
	 * 处理参数信息
	 *
	 * @return
	 * @throws BusinessException
	 */
	void processParam() throws BusinessException {

		// TODO 进行简单校验

		//业务控制类型
		this.busictrlType = BctpControlBsUtils.queryTopBusictrlType(this.ctrlScheme.getPk_busictrltype());
		/*
		 * 处理维度信息
		 */
		if(this.ctrlDims != null && this.ctrlDims.length > 0) {


			for(int i=0;i<this.busiCtrlDims.length;i++) {

				this.busiCtrlDimMap.put(busiCtrlDims[i].getPk_ctrldim(), busiCtrlDims[i]);

				//记录需要向上级匹配的业务控制维度
				if(busiCtrlDims[i].getIsmatchparent() != null && busiCtrlDims[i].getIsmatchparent().booleanValue()) {
					busiCtrlDimList_matchup.add(busiCtrlDims[i]);
				}

			}
			//按照向上匹配顺序排序
			VOSortUtils.ascSort(busiCtrlDimList_matchup, new String[] {BusiCtrlDimBVO.MATCHPARENTORDER});

			StringBuilder ctrlDimStr = new StringBuilder();
			for(int i=0;i<this.ctrlDims.length;i++) {
				this.ctrlDimMap.put(ctrlDims[i].getId(), ctrlDims[i]);
				ctrlDimStr.append("[");
				ctrlDimStr.append(ctrlDims[i].getName());
				ctrlDimStr.append("]");
			}
			this.ctrlDimStr = ctrlDimStr.toString();
		}

		/*
		 * 处理单据动作
		 */
		BusiConfigBillactionVO[] billActionVos = (BusiConfigBillactionVO[]) aggBusiConfigVo.getChildren(BusiConfigBillactionVO.class);
		this.billActionMap = new HashMap<String, BusiConfigBillactionVO>();
		for (int i = 0; i < billActionVos.length; i++) {

			billActionMap.put(billActionVos[i].getCode(), billActionVos[i]);

			if (billActionVos[i].getCode().equals(actionCode)) {

				if(billActionVos[i].getEnablestate() != null && billActionVos[i].getEnablestate() == EnableStateEnum.ENABLESTATE_ENABLE.toIntValue()) {
					this.setBillActionVo(billActionVos[i]);
				}

			}

		}

		this.setDimMapVos((BusiConfigDimmapVO[]) aggBusiConfigVo.getChildren(BusiConfigDimmapVO.class));

		/*
		 * 2、将参数单据VO转换为执行监控信息
		 */
		this.aggBusiCtrlVoFromParam = BctpControlBsUtils.getCtrlVoFromParam(aggBusiConfigVo, busiCtrlDimMap, ctrlDimMap, ctrlScheme, ctrlSchemeb, paramVo);
		if (this.oriParamVo != null)
			this.oriAggBusiCtrlVoFromParam = BctpControlBsUtils.getCtrlVoFromParam(aggBusiConfigVo, busiCtrlDimMap, ctrlDimMap, ctrlScheme, ctrlSchemeb, oriParamVo);

//		this.isJoinCtrl = this.aggBusiCtrlVoFromParam.getParentVO().getIsjoinctrl();

		// 找不到对应动作时直接返回
		if (this.billActionVo == null) {
//			throw new BusinessException("未找到#"+actionCode+"#对应的单据动作，请检查业务单据配置。");
			Logger.error("业务控制平台：未找到#"+actionCode+"#启用的单据动作，请检查业务单据配置。");
			return;
		}

	}

	/**
	 * 初始化控制规则信息
	 *
	 * @return idcodes
	 * @throws BusinessException
	 */
	private String[] initCtrlRuleFromDB(String[] idCodes) throws BusinessException {

		SqlBuilder sql = new SqlBuilder();

		sql.append("select bcr.* from "+BusiCtrlRuleVO.getDefaultTableName()+" bcr");
		sql.append(" inner join hrpbctp_busictrl bc on bcr.pk_busictrl = bc.pk_busictrl and bc.dr = 0 and bc.isjoinctrl = '"+isJoinCtrl.toString()+"'");
		sql.append(" where bcr.dr", 0);
		sql.append(" and bcr.idcode in (");
		sql.append(
				" select distinct isnull(b.idcode,a.idcode) from " + BusiCtrlRuleVO.getDefaultTableName() + " a");
		sql.append(" left join " + BusiCtrlRuleVO.getDefaultTableName()
				+ " b on isnull(b.dr,0) = 0 and a.pk_busictrl = b.pk_busictrl and isnull(a.combinectrlno,0) = isnull(b.combinectrlno,1) ");
		sql.append(" where isnull(a.dr,0) = 0 and a.idcode ", idCodes);
		sql.append(")");

		/*
		 * 查询业务控制规则 要同时查询出分组控制符相同的控制规则
		 */
		List<BusiCtrlRuleVO> ctrlRuleVoList = (List<BusiCtrlRuleVO>)getDAO().executeQuery(sql.toString(), new BeanListProcessor(BusiCtrlRuleVO.class));
		if(ctrlRuleVoList != null){

			this.ctrlRuleMapFromDb = new HashMap<String, BusiCtrlRuleVO>();
			// 按照分组控制编号进行分组
			this.combCtrlRuleMaplFromDb = new MapList<String, BusiCtrlRuleVO>();

			BusiCtrlRuleVO tempCtrlRule;
			for (int i = 0; i < ctrlRuleVoList.size(); i++) {

				tempCtrlRule = ctrlRuleVoList.get(i);

				if (ctrlRuleMapFromDb.containsKey(tempCtrlRule.getIdcode())) {
					throw new BusinessException("根据当前idcode#" + tempCtrlRule.getIdcode() + "#查询出多条业务控制规则，请联系技术人员进行排查！");
				}

				this.ctrlRuleMapFromDb.put(tempCtrlRule.getIdcode(), tempCtrlRule);
				/*
				 * 合并控制处理 key：业务控制信息表头主键+分组控制编号
				 */
				if (tempCtrlRule.getCombinectrlno() != null)
					this.combCtrlRuleMaplFromDb.put(tempCtrlRule.getPk_busictrl() + tempCtrlRule.getCombinectrlno(), tempCtrlRule);

			}

		}


		return this.ctrlRuleMapFromDb.keySet().toArray(new String[0]);

	}

	/**
	 * 初始化控制数据
	 *
	 * @return idcodes
	 * @throws BusinessException
	 */
	protected void initCtrlDataFromDB(String[] idCodes) throws BusinessException {

		this.ctrlDataMapFromDb = queryCtrlDataFromDB(idCodes);

	}

	/**
	 * 向上级匹配数据
	 * @return idcodes
	 * @throws BusinessException
	 */
//	private void matchUpForParamCtrlData(String[] idCodes) throws BusinessException {
//
//		if(this.busiCtrlDimList_matchup.size() > 0) {//存在向上匹配的业务控制维度时才进行向上匹配
//
//			//从数据库中查询相关的业务控制维度
//			this.queryCtrlDataFromDB(idCodes);
//
//
//		}
//
//	}

	/**
	 * 查询控制数据
	 *
	 * @return idcodes
	 * @throws BusinessException
	 */
	public Map<String, BusiCtrlDataVO> queryCtrlDataFromDB(String[] idCodes) throws BusinessException {

		Map<String, BusiCtrlDataVO> result = new HashMap<String, BusiCtrlDataVO>();

		SqlBuilder sql = new SqlBuilder();

		sql.append("select bcd.* from hrpbctp_busictrldata bcd");
		sql.append(" inner join hrpbctp_busictrl bc on bcd.pk_busictrl = bc.pk_busictrl and bc.dr = 0 and bc.isjoinctrl = '"+isJoinCtrl.toString()+"'");
		sql.append(" where bcd.dr", 0);
		sql.append(" and bcd.idcode", idCodes);

		/*
		 * 查询业务控制数信息
		 */
		List<BusiCtrlDataVO> ctrlDataVoList = (List<BusiCtrlDataVO>)getDAO().executeQuery(sql.toString(), new BeanListProcessor(BusiCtrlDataVO.class));

		if(ctrlDataVoList != null) {

			BusiCtrlDataVO tempCtrlData;
			for (int i = 0; i < ctrlDataVoList.size(); i++) {

				tempCtrlData = ctrlDataVoList.get(i);

				if (result.containsKey(tempCtrlData.getIdcode())) {
					throw new BusinessException("根据当前idcode#" + tempCtrlData.getIdcode() + "#查询出多条业务控制数据，请联系技术人员进行排查！");
				}

				result.put(tempCtrlData.getIdcode(), tempCtrlData);

			}

		}

		return result;

	}

	/**
	 * 处理数据
	 *
	 * @param operateData
	 * @return
	 * @throws BusinessException
	 */
	private Object processData(BctpControlOperateDataBean operateData) throws BusinessException {

		for (int i = 0; i < this.operators.size(); i++) {

			this.operators.get(i).operate(this, operateData);

		}

		return null;

	}

	/**
	 * 执行业务控制
	 * @param operateData
	 * @return
	 * @throws BusinessException
	 */
	protected abstract boolean processControl(BctpControlOperateDataBean processData) throws BusinessException;

	/**
	 * 处理业务控制结果 如果存在ERROR类型的消息，直接抛出异常 如果存在ASK类型的消息，直接抛出异常，由前端进行处理
	 *
	 * @param processData
	 * @return
	 * @throws BusinessException
	 */
	protected boolean processControlMessage() throws Exception {

		boolean flag = true;

		//如果当前单据动作的业务控制操作包含减少预占或者减少执行，则不提示控制错误或者信息
//		if((this.getBillActionVo().getReduceoccu() != null && this.getBillActionVo().getReduceoccu().booleanValue())
//			|| (this.getBillActionVo().getReductexec() != null && this.getBillActionVo().getReductexec().booleanValue())){
//
//			this.getResultMessage().clear();
//			flag = true;
//
//		}else {

		String message = this.getResultMessage().get(BctpControlMessageUtils.ERROR);
		if (message != null && !"".contentEquals(message)) {
			flag = false;
			throw new BusinessException(message);
		}

		// 此版本先不实现询问的情况
		message = this.getResultMessage().get(BctpControlMessageUtils.ASK);
		if (message != null && !"".contentEquals(message)) {
			flag = false;
			throw new BusinessException(message);
		}

//		}

		return flag;

	}

	/**
	 * 获取消息头
	 * @param messageType
	 * @return
	 */
	protected String getErrorMessageTitle() {

//		String messageTitle = this.getBusictrlType().getName() + this.getCtrlDimStr();

//		String messageTitle = "控制维度：" + this.busiCtrlDim.getName() + "\n控制方案：" + this.getCtrlScheme().getName();

		String messageTitle = this.getBusictrlType().getName();

		return messageTitle;

	}

	/**
	 * 初始化业务控制操作策略 当前存在的急诊操作策略 增加业务控制 更新业务控制 删除业务控制 增加预占 减少预占 增加执行 减少执行
	 * 需要注意的是，删除、减少类的操作要在前面执行
	 *
	 * @return
	 */
	private void initProcessors() {

		// 删除业务控制
		if (this.billActionVo.getDeldata().booleanValue()) {
			operators.add(new PushDataForDelete());
		}
		// 减少冻结
		if (this.billActionVo.getReducefreeze().booleanValue()) {
			operators.add(new PushDataForUpdateReduceFreeze());
		}
		// 更新业务控制
		if (this.billActionVo.getUpddata().booleanValue()) {
			operators.add(new PushDataForUpdate());
		}
		// 增加业务控制
		if (this.billActionVo.getInsdata().booleanValue()) {
			operators.add(new PushDataForInsert());
		}
		// 增加冻结
		if (this.billActionVo.getAddfreeze().booleanValue()) {
			operators.add(new PushDataForUpdateAddFreeze());
		}


		// 减少执行
		if (this.billActionVo.getReductexec().booleanValue()) {
			operators.add(new ExecForSubExec());
		}
		// 减少预占
		if (this.billActionVo.getReduceoccu().booleanValue()) {
			operators.add(new ExecForSubOccu());
		}
		// 增加执行
		if (this.billActionVo.getAddexec().booleanValue()) {
			operators.add(new ExecForAddExec());
		}
		// 增加预占
		if (this.billActionVo.getAddoccu().booleanValue()) {
			operators.add(new ExecForAddOccu());
		}

	}

	/**
	 * 初始化插件
	 *
	 * @param aggBusiConfigVo
	 * @return
	 * @throws BusinessException
	 */
	protected Object initPlugins(AggBusiConfigVO aggBusiConfigVo) throws BusinessException {

		BusiConfigPluginregVO[] plugins = (BusiConfigPluginregVO[]) aggBusiConfigVo.getChildren(BusiConfigPluginregVO.class);

		if (plugins != null) {

			// 按照执行顺序排序
			VOSortUtils.ascSort(plugins, new String[] { BusiConfigPluginregVO.EXECINDEX });

			BusiConfigPluginregVO tempPlugin;
			for (int i = 0; i < plugins.length; i++) {
				tempPlugin = plugins[i];

				/*
				 * 判断当前动作是否需要执行插件
				 * 1、未指定单据动作时可以执行插件
				 * 2、当前单据动作为指定执行的单据动作才可以执行插件
				 */
				List<String> pluginActionsList = null;
				if(tempPlugin.getPluginactions() !=null && !"".equals(tempPlugin.getPluginactions())){
					pluginActionsList = Arrays.asList(tempPlugin.getPluginactions().split(","));
				}

				if(pluginActionsList == null || pluginActionsList.contains(this.getBillActionVo().getCode())) {

					// 获取插件类实例
					IBctpControlPlugin plugin = getPlugin(tempPlugin);
					// 前插件
					if (tempPlugin.getDobefore() != null && tempPlugin.getDobefore().booleanValue()) {
						beforePlugins.add(plugin);
					}

					// 后插件
					if (tempPlugin.getDoafter() != null && tempPlugin.getDoafter().booleanValue()) {
						afterPlugins.add(plugin);
					}

				}

			}

		}

		return null;

	}

	/**
	 * 获取插件类实例
	 *
	 * @param pluginClassFullName
	 * @return
	 * @throws BusinessException
	 */
	private IBctpControlPlugin getPlugin(BusiConfigPluginregVO pluginVo) throws BusinessException {

		IBctpControlPlugin plugin = null;
		try {
			plugin = (IBctpControlPlugin) (Class.forName(pluginVo.getPluginclass()).newInstance());
		} catch (Exception e) {
			throw new BusinessException("实例化插件类失败，请检查业务单据配置(插件编码：" + pluginVo.getCode() + ")：\n" + e.getMessage());
		}

		return plugin;
	}

	/**
	 * 执行前插件
	 *
	 * @return
	 * @throws BusinessException
	 */
	private Object processPlugin_before() throws Exception {

		IBctpControlPlugin curPlugin = null;

		Object returnValue = null;

		try {

			if (beforePlugins != null) {

				for (int i = 0; i < beforePlugins.size(); i++) {

					curPlugin = beforePlugins.get(i);
					returnValue = curPlugin.handleBefore(this);

					if(returnValue instanceof Boolean) {//Boolean类型的返回结果代表要中断后续执行
						Logger.warn("业务控制平台：前业务插件"+curPlugin.getClass().getName()+" 返回结果false，执行中断。");
						break;
					}

				}

			}


		} catch(Exception e) {

			Logger.error("业务控制平台：前业务插件"+curPlugin.getClass().getName()+"执行异常："+e.getMessage());
			throw new BusinessException(e.getMessage());

		}

		return returnValue;

	}

	/**
	 * 执行后插件
	 *
	 * @return
	 * @throws BusinessException
	 */
	private Object processPlugin_after() throws Exception {

		IBctpControlPlugin curPlugin = null;

		try {

			if (afterPlugins != null) {

				for (int i = 0; i < afterPlugins.size(); i++) {
					curPlugin = afterPlugins.get(i);
					curPlugin.handleAfter(this);
				}

			}

		} catch(Exception e) {

			Logger.error("业务控制平台：后业务插件"+curPlugin.getClass().getName()+"执行异常："+e.getMessage());
			throw new BusinessException(e.getMessage());

		}


		return null;

	}

	/**
	 * 通过对比 参数执行数据 与 原始参数执行数据 获取到真实的执行数据 真实执行数据 = 新的执行数据 - 原始的执行数据
	 *
	 * @param ctrlDataMap
	 * @param oriCtrlDataMap
	 * @return
	 */
	public abstract Map<String, BusiCtrlDataVO> getActualOperateData(Map<String, BusiCtrlDataVO> ctrlDataMap,
																	 Map<String, BusiCtrlDataVO> oriCtrlDataMap);

	/**
	 * 数据库操作
	 * @param operateData
	 * @return
	 * @throws BusinessException
	 */
	protected Object processDb(BctpControlOperateDataBean operateData) throws BusinessException {

		try {

			//只做校验时不进行数据库操作
			if(this.billActionVo.getOnlycheck() != null && this.billActionVo.getOnlycheck().booleanValue())
				return null;

			/*
			 * 新增业务控制单据
			 */
			if (operateData.getInsAggBusiCtrlVo() != null) {

				// 插入业务控制数据单据
				AggBusiCtrlVO aggVo = operateData.getInsAggBusiCtrlVo();
				//EDIT BY WW 2024-08-16 处理结转的情况是不能设置为空，在PushDataForInsert和PushDataForUpdate中进行处理
//				aggVo.setChildren(BusiCtrlDetailVO.class, new BusiCtrlDetailVO[0]);

				AggBusiCtrlVO[] results = NCLocator.getInstance().lookup(IBusiCtrlVOService.class)
						.saveAggBusiCtrlVO(aggVo);
				AggBusiCtrlVO result = results[0];

				// 更新业务控制规则的业务控制明细主键
				String sql_ctrule = "update "+BusiCtrlRuleVO.getDefaultTableName()+" a set a.pk_busictrldata = "
						+ " (select b.pk_busictrldata from hrpbctp_busictrldata b "
						+ " where b.dr = 0 and b.pk_busictrl = '" + result.getPrimaryKey() + "' and a.idcode = b.idcode)"
						+ " where a.dr = 0 and a.pk_busictrl = '" + result.getPrimaryKey() + "'";

				int updCount = this.getDAO().executeUpdate(sql_ctrule);

				operateData.setInsAggBusiCtrlVo(result);

			}

			/*
			 * 删除业务控制单据
			 */
			if (operateData.getDelAggBusiCtrlVo() != null) {

				AggBusiCtrlVO delVo = operateData.getDelAggBusiCtrlVo();

				Map<String, String> tsMap = new HashMap<String, String>();
				tsMap.put(delVo.getPrimaryKey(), delVo.getParentVO().getTs().toString());

				AggBusiCtrlVO[] results = NCLocator.getInstance().lookup(IBusiCtrlVOService.class)
						.deleteAggBusiCtrlVOs(tsMap);

			}

			/*
			 * 更新业务控制数据
			 */
			if (operateData.getUpdControlDataMap() != null && operateData.getUpdControlDataMap().size() > 0) {

				BusiCtrlDataVO[] ctrlDataVos = operateData.getUpdControlDataMap().values()
						.toArray(new BusiCtrlDataVO[0]);
				// 更新业务控制数据
				BatchOperateVO batchVO = new BatchOperateVO();
				batchVO.setUpdObjs(ctrlDataVos);
				BatchSaveAction saveAction = new BatchSaveAction();
				batchVO = saveAction.batchSave(batchVO);

			}

			/*
			 * 删除业务控制数据
			 */
			if(operateData.getDelControlDataVos() != null && operateData.getDelControlDataVos().size() > 0) {

				// 删除业务控制数据
				List<BusiCtrlDataVO> ctrlDataVos = operateData.getDelControlDataVos();
				// 删除业务控制规则
				List<BusiCtrlRuleVO> ctrlRuleVos = operateData.getDelControlRuleVos();

				if(ctrlDataVos.size() == ctrlRuleVos.size()) {

					this.getDAO().deleteVOList(ctrlDataVos);
					this.getDAO().deleteVOList(ctrlRuleVos);

//				BatchOperateVO batchVO1 = new BatchOperateVO();
//				batchVO1.setDelObjs(ctrlDataVos.toArray(new BusiCtrlDataVO[0]));
//				BatchSaveAction saveAction1 = new BatchSaveAction();
//				batchVO1 = saveAction1.batchSave(batchVO1);
//
//				BatchOperateVO batchVO2 = new BatchOperateVO();
//				batchVO2.setDelObjs(ctrlRuleVos.toArray(new BusiCtrlRuleVO[0]));
//				BatchSaveAction saveAction2 = new BatchSaveAction();
//				batchVO2 = saveAction2.batchSave(batchVO2);

				}else {

					throw new BusinessException("删除业务控制数据失败：控制数据和控制规则数量不一致，请联系技术人员进行排查。");

				}

			}

			/*
			 * 新增业务控制数据
			 */
			if (operateData.getInsControlDataMap() != null && operateData.getInsControlDataMap().size() > 0) {

				BusiCtrlDataVO[] ctrlDataVos = operateData.getInsControlDataMap().values()
						.toArray(new BusiCtrlDataVO[0]);
				String[] pk_busictrldatas = this.getDAO().insertVOArray(ctrlDataVos);

				/*
				 * 新增执行数据时要同时新增控制信息 将控制信息与业务控制数信息进行关联
				 */
				Map<String, BusiCtrlRuleVO> ctrlRuleData = operateData.getInsControlRuleMap();
				String key = null;
				BusiCtrlRuleVO tempCtrlRuleVo = null;
				for (int i = 0; i < ctrlDataVos.length; i++) {

					key = ctrlDataVos[i].getIdcode();
					tempCtrlRuleVo = ctrlRuleData.get(key);
					tempCtrlRuleVo.setPk_busictrldata(pk_busictrldatas[i]);

				}

				BusiCtrlRuleVO[] ctrlRuleVos = ctrlRuleData.values().toArray(new BusiCtrlRuleVO[0]);
				// 新增业务控制规则
				BatchOperateVO batchVO = new BatchOperateVO();
				batchVO.setAddObjs(ctrlRuleVos);
				BatchSaveAction saveAction = new BatchSaveAction();
				batchVO = saveAction.batchSave(batchVO);

			}

			/*
			 * 更新业务控制数据
			 */
			if (operateData.getUpdControlDataMap() != null && operateData.getUpdControlDataMap().size() > 0) {

				BusiCtrlDataVO[] ctrlDataVos = operateData.getUpdControlDataMap().values()
						.toArray(new BusiCtrlDataVO[0]);
				// 更新业务控制数据
				BatchOperateVO batchVO = new BatchOperateVO();
				batchVO.setUpdObjs(ctrlDataVos);
				BatchSaveAction saveAction = new BatchSaveAction();
				batchVO = saveAction.batchSave(batchVO);

			}

			/*
			 * 删除业务控制执行明细
			 */
			if (operateData.getDelControlDetails() != null && operateData.getDelControlDetails().size() > 0) {

				List<BusiCtrlDetailVO> ctrlDetails = operateData.getDelControlDetails();

				this.deleteControlDetails(ctrlDetails);

			}

			/*
			 * 新增业务控制执行明细
			 */
			if (operateData.getInsControlDetails() != null && operateData.getInsControlDetails().size() > 0) {

				//是否需要新增明细
				boolean isinsdetail = this.getBillActionVo().getIsinsdetail() == null ? false : this.getBillActionVo().getIsinsdetail().booleanValue();

				if(isinsdetail) {

					// 将同一行单据明细的操作记录做合并
					BusiCtrlDetailVO[] ctrlDetailVos = BctpControlBsUtils.combineCtrlDetail(operateData.getInsControlDetails());

					// 更新业务控制数据
					BatchOperateVO batchVO = new BatchOperateVO();
					batchVO.setAddObjs(ctrlDetailVos);
					BatchSaveAction saveAction = new BatchSaveAction();
					batchVO = saveAction.batchSave(batchVO);

				}

			}

		} catch(Exception e) {

			throw new BusinessException("控制数据保存失败：\n" + e.getMessage());

		}

		return null;

	}

	/**
	 * 删除执行明细
	 *
	 * @param ctrlDetails
	 * @throws BusinessException
	 */
	private void deleteControlDetails(List<BusiCtrlDetailVO> ctrlDetails) throws BusinessException {

		DBTool tool = new DBTool();
		Connection connection = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {

			String sql = "delete from hrpbctp_busictrldetail where idcode = ? and pk_cdbillid = ? and pk_cdbillbid = ? and cdbillaction = ?";

			// 删除所有明细时，去掉一个条件，每一行数据明细只执行一次就行了
			if ("ALL".equals(this.billActionVo.getDelactions())) {
				sql = "delete from hrpbctp_busictrldetail where idcode = ? and pk_cdbillid = ? and pk_cdbillbid = ?";
			}

			connection = tool.getConnection();

			stmt = connection.prepareStatement(sql);

			BusiCtrlDetailVO tempCtrlDetail;
			List<String> uniqueKeys = new ArrayList<String>();
			String uniqueKey = null;
			for (int i = 0; i < ctrlDetails.size(); i++) {

				tempCtrlDetail = ctrlDetails.get(i);

				// 单据主键+单据明细主键唯一
				uniqueKey = tempCtrlDetail.getPk_cdbillid() + tempCtrlDetail.getPk_cdbillbid();

				// 唯一标识码
				stmt.setString(1, tempCtrlDetail.getIdcode());
				// 操作单据主键
				stmt.setString(2, tempCtrlDetail.getPk_cdbillid());
				// 操作单据明细主键
				stmt.setString(3, tempCtrlDetail.getPk_cdbillbid());
				// 单据动作
				if ("ALL".equals(this.billActionVo.getDelactions())) {// 删除所有明细时，去掉一个条件，每一行数据明细只执行一次就行了

					if (uniqueKeys.contains(uniqueKey)) {
						continue;
					}

				} else {

					stmt.setString(4, tempCtrlDetail.getCdbillaction());

				}

				uniqueKeys.add(uniqueKey);
				// 添加批处理SQL
				stmt.addBatch();

			}

			stmt.executeBatch();

		} catch (Exception e) {
			throw new BusinessException("删除执行明细失败：" + e.getMessage());
		} finally {

			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException ex) {
					Logger.error(ex.getMessage());
				}
			}
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException ex) {
					Logger.error(ex.getMessage());
				}
			}
			if (connection != null) {
				try {
					connection.close();
				} catch (SQLException ex) {
					Logger.error(ex.getMessage());
				}
			}
		}
	}

	private BaseDAO dao;

	public BaseDAO getDAO() {
		if (dao == null)
			dao = new BaseDAO();
		return dao;
	}

	private IUifService service;

	public IUifService getService() throws UifException {
		if (this.service == null) {
			try {
				this.service = (IUifService)NCLocator.getInstance().lookup(IUifService.class.getName());
			} catch (ComponentException e) {
				Logger.warn("can't find " + e.getComponentName(), e);
				throw new UifException();
			}
		}
		return this.service;
	}

//	public String getPk_group() {
//		return pk_group;
//	}
//
//	public void setPk_group(String pk_group) {
//		this.pk_group = pk_group;
//	}
//
//	public String getPk_org() {
//		return pk_org;
//	}
//
//	public void setPk_org(String pk_org) {
//		this.pk_org = pk_org;
//	}
//
//	public String getBilltype() {
//		return billtype;
//	}
//
//	public void setBilltype(String billtype) {
//		this.billtype = billtype;
//	}
//
//	public String getTranstype() {
//		return transtype;
//	}
//
//	public void setTranstype(String transtype) {
//		this.transtype = transtype;
//	}

//	public String getActionCode() {
//		return actionCode;
//	}
//
//	public void setActionCode(String actionCode) {
//		this.actionCode = actionCode;
//	}

	public BusictrlSchemeVO getCtrlScheme() {
		return ctrlScheme;
	}

//	public void setCtrlScheme(BusictrlSchemeVO ctrlScheme) {
//		this.ctrlScheme = ctrlScheme;
//	}

	public BusictrlSchemeBVO getCtrlSchemeb() {
		return ctrlSchemeb;
	}

//	public void setCtrlSchemeb(BusictrlSchemeBVO ctrlSchemeb) {
//		this.ctrlSchemeb = ctrlSchemeb;
//	}

//	public AggregatedValueObject getParamVo() {
//		return paramVo;
//	}

//	public void setParamVo(AggregatedValueObject paramVo) {
//		this.paramVo = paramVo;
//	}

//	public AggregatedValueObject getOriParamVo() {
//		return oriParamVo;
//	}

	public void setOriParamVo(AggregatedValueObject oriParamVo) {
		this.oriParamVo = oriParamVo;
	}

	public BusiConfigVO getBusiConfigVo() {
		return busiConfigVo;
	}

	public void setBusiConfigVo(BusiConfigVO busiConfigVo) {
		this.busiConfigVo = busiConfigVo;
	}

	public BusiConfigDimmapVO[] getDimMapVos() {
		return billMapVos;
	}

	public void setDimMapVos(BusiConfigDimmapVO[] billMapVos) {
		this.billMapVos = billMapVos;
	}

	public BusiConfigBillactionVO getBillActionVo() {
		return billActionVo;
	}

	public void setBillActionVo(BusiConfigBillactionVO billActionVo) {
		this.billActionVo = billActionVo;
	}

	public void setBillActionMap(Map<String, BusiConfigBillactionVO> billActionMap) {
		this.billActionMap = billActionMap;
	}

	public Map<String, BusiConfigBillactionVO> getBillActionMap() {
		return billActionMap;
	}

	public AggBusiCtrlVO getAggBusiCtrlVoFromParam() {
		return aggBusiCtrlVoFromParam;
	}

	public void setAggBusiCtrlVoFromParam(AggBusiCtrlVO aggBusiCtrlVoFromParam) {
		this.aggBusiCtrlVoFromParam = aggBusiCtrlVoFromParam;
	}

	public AggBusiCtrlVO getOriAggBusiCtrlVoFromParam() {
		return oriAggBusiCtrlVoFromParam;
	}

	public void setOriAggBusiCtrlVoFromParam(AggBusiCtrlVO oriAggBusiCtrlVoFromParam) {
		this.oriAggBusiCtrlVoFromParam = oriAggBusiCtrlVoFromParam;
	}

	/**
	 * 获取从参数单据中转换的控制规则
	 *
	 * @return
	 * @throws BusinessException
	 */
	public Map<String, BusiCtrlRuleVO> getCtrlRuleMapFromParam() throws BusinessException {

		if (ctrlRuleMapFromParam == null) {

			BusiCtrlRuleVO[] ctrlRules = (BusiCtrlRuleVO[]) this.getAggBusiCtrlVoFromParam()
					.getChildren(BusiCtrlRuleVO.class);
			ctrlRuleMapFromParam = BctpControlPubUtils.getControlRuleVoMap(ctrlRules);

		}
		return ctrlRuleMapFromParam;
	}

	public void setCtrlRuleMapFromParam(Map<String, BusiCtrlRuleVO> ctrlRuleMapFromParam) throws BusinessException {

		this.ctrlRuleMapFromParam = ctrlRuleMapFromParam;

	}

	/**
	 * 获取从原始参数单据中转换的控制规则
	 *
	 * @return
	 * @throws BusinessException
	 */
	public Map<String, BusiCtrlRuleVO> getOriCtrlRuleMapFromParam() throws BusinessException {

		if (oriCtrlRuleMapFromParam == null) {

			BusiCtrlRuleVO[] ctrlRules = (BusiCtrlRuleVO[]) this.getOriAggBusiCtrlVoFromParam()
					.getChildren(BusiCtrlRuleVO.class);
			oriCtrlRuleMapFromParam = BctpControlPubUtils.getControlRuleVoMap(ctrlRules);

		}
		return oriCtrlRuleMapFromParam;
	}

	public void setOriCtrlRuleMapFromParam(Map<String, BusiCtrlRuleVO> oriCtrlRuleMapFromParam)
			throws BusinessException {

		this.oriCtrlRuleMapFromParam = oriCtrlRuleMapFromParam;

	}

	public Map<String, BusiCtrlRuleVO> getCtrlRuleMapFromDb() {
		return ctrlRuleMapFromDb;
	}

	public void setCtrlRuleMapFromDb(Map<String, BusiCtrlRuleVO> ctrRuleMapFromDb) {
		this.ctrlRuleMapFromDb = ctrRuleMapFromDb;
	}

	public MapList<String, BusiCtrlRuleVO> getCombCtrlRuleMaplFromDb() {
		return combCtrlRuleMaplFromDb;
	}

	public void setCombCtrlRuleMaplFromDb(MapList<String, BusiCtrlRuleVO> combCtrlRuleMaplFromDb) {
		this.combCtrlRuleMaplFromDb = combCtrlRuleMaplFromDb;
	}

	/**
	 * 不对外提供直接访问的方法
	 *
	 * @return
	 */
	private Map<String, BusiCtrlDataVO> getCtrlDataMapFromDb() {
		return ctrlDataMapFromDb;
	}

	/**
	 * 确保信息不被外部修改，此处对外提供克隆对象
	 *
	 * @return
	 */
	public Map<String, BusiCtrlDataVO> getCtrlDataMapFromDb_clone() {

		Map<String, BusiCtrlDataVO> ctrlDataMapFromDb_clone = null;
		if (ctrlDataMapFromDb != null) {

			ctrlDataMapFromDb_clone = new HashMap<String, BusiCtrlDataVO>();

			for (String key : ctrlDataMapFromDb.keySet()) {

				ctrlDataMapFromDb_clone.put(key, (BusiCtrlDataVO) ctrlDataMapFromDb.get(key).clone());

			}

		}

		return ctrlDataMapFromDb_clone;
	}

	/**
	 * 不对外提供直接访问的方法
	 *
	 * @return
	 */
//	private Map<String, BusiCtrlDataVO> getCtrlDataMapFromDb_matchup() {
//		return ctrlDataMapFromDb_matchup;
//	}

	/**
	 * 确保信息不被外部修改，此处对外提供克隆对象
	 *
	 * @return
	 */
//	public Map<String, BusiCtrlDataVO> getCtrlDataMapFromDb_matchup_clone() {
//
//		Map<String, BusiCtrlDataVO> ctrlDataMapFromDb_matchup_clone = null;
//		if (ctrlDataMapFromDb_matchup != null) {
//
//			ctrlDataMapFromDb_matchup_clone = new HashMap<String, BusiCtrlDataVO>();
//
//			for (String key : ctrlDataMapFromDb_matchup.keySet()) {
//
//				ctrlDataMapFromDb_matchup_clone.put(key, (BusiCtrlDataVO) ctrlDataMapFromDb_matchup.get(key).clone());
//
//			}
//
//		}
//
//		return ctrlDataMapFromDb_matchup_clone;
//	}

	/**
	 * 从执行明细中获取每个业务控制维度对应的执行数
	 *
	 * @return
	 * @throws BusinessException
	 */
	public Map<String, UFDouble> getIdCodeExecuteAmountMap() throws BusinessException {

		Map<String, UFDouble> executeAmountMap = new HashMap<String, UFDouble>();

		List<BusiCtrlDetailVO> ctrlDetails = operateData.getInsControlDetails();
		if (ctrlDetails != null && ctrlDetails.size() > 0) {

			BusiCtrlDetailVO tempCtrlData;
			for (int i = 0; i < ctrlDetails.size(); i++) {

				tempCtrlData = ctrlDetails.get(i);

				UFDouble tempOccuAmount = executeAmountMap.get(tempCtrlData.getIdcode());
				tempOccuAmount = tempOccuAmount == null ? UFDouble.ZERO_DBL : tempOccuAmount;

				if(this.busiConfigVo.getBusiscenemode().equals(BusisceneModeEnum.PRICE.toStringValue())) {//价格控制时，取最大值
					tempOccuAmount = (tempOccuAmount.compareTo(tempCtrlData.getAmount()) > 0) ? tempOccuAmount : tempCtrlData.getAmount();
				}else {//其他情况（金额控制、数量控制）时取合计值
					tempOccuAmount = tempOccuAmount.add(tempCtrlData.getAmount());
				}

				executeAmountMap.put(tempCtrlData.getIdcode(), tempOccuAmount);
			}

		}

		return executeAmountMap;
	}

	/**
	 * 匹配上级的控制数据idcode对照
	 *key：参数ctrldata的idcode，value：匹配上级ctrldata的idcode
	 */
	public Map<String, String> getCtrlDataIdCodeMap_matchup() {
		return ctrlDataIdCodeMap_matchup;
	}
	//	public void setCtrlDataIdCodeMap_matchup(Map<String, String> ctrlDataIdCodeMap_matchup) {
//		this.ctrlDataIdCodeMap_matchup = ctrlDataIdCodeMap_matchup;
//	}
	public BusictrlTypeVO getBusictrlType() {
		return busictrlType;
	}

	public CtrlDimVO[] getCtrlDims() {
		return ctrlDims;
	}

	public String getCtrlDimStr() {
		return ctrlDimStr == null ? "" : ctrlDimStr;
	}

	public void setCtrlDataMapFromDb(Map<String, BusiCtrlDataVO> ctrlDataMapFromDb) {
		this.ctrlDataMapFromDb = ctrlDataMapFromDb;
	}

	public Map<String, String> getResultMessage() {
		return resultMessage;
	}

	public Map<String, Object> getExtendObjMap() {
		return extendObjMap;
	}

	/**
	 * 找不到业务控制数据时是否控制
	 * @return
	 */
	public boolean isNoCtrlDataCtrl() {
		return isNoCtrlDataCtrl;
	}

	private  IUifService dbService;
	public IUifService getDbService() throws UifException {
		if (dbService == null)
			try {
				dbService = (IUifService) NCLocator.getInstance().lookup(IUifService.class.getName());
			} catch (ComponentException e) {
				Logger.warn("can't find " + e.getComponentName(), (Throwable) e);
				throw new UifException();
			}
		return dbService;
	}

	public Map<String, BusiCtrlDataVO> matchUp(BusiCtrlDataVO[] ctrlDatas,Map<String,String> ctrlDataIdCodeMap_matchup,boolean isThrowNoCtrlDataError) throws BusinessException{

		return BctpControlDimValueMatchUpUtils.matchUp(this, ctrlDimMap, busiCtrlDimList_matchup, ctrlDatas, ctrlDataIdCodeMap_matchup,isThrowNoCtrlDataError);

	}

	public BctpControlOperateDataBean getOperateData() {
		return operateData;
	}
//	public void setOperateData(BctpControlOperateDataBean operateData) {
//		this.operateData = operateData;
//	}

}
